package csci5828.search;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.scribe.builder.ServiceBuilder;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.oauth.OAuthService;

import com.google.gson.Gson;
import com.yelp.v2.Business;
import com.yelp.v2.Reviews;
import com.yelp.v2.YelpSearchResult;
import com.yelp.v2.YelpV2API;

import csci5828.configuration.ConfigurationManager;

public class YelpSearch implements Search {
	
	// Instance Vars
	private static final String CONSUMER_KEY = "yelp.consumer.key";
	private static final String CONSUMER_SECRET = "yelp.consumer.secret";
	private static final String TOKEN = "yelp.token";
	private static final String TOKEN_SECRET = "yelp.token.secret";
	
	private final Logger logger = Logger.getLogger(getClass());
	private List<SearchResult> mySRList = new ArrayList<SearchResult>();
	private int maxBusiness;
	private String location;
	private YelpSortParam sort;
	double myStartTime = 0;
	double myEndTime = 0; 
	
	// Extends result functionality to allow for sorting
	public enum YelpSortParam
	{
		DEFAULT {
		    public String toString() {  return "0";    }},
		DISTANCE {
		    public String toString() {  return "1";    }},
		BEST_RATED {
		    public String toString() {  return "2";    }}
	};
	
	// Constructor
	public YelpSearch(String location)
	{
		this(location, 1);
	}
	
	public YelpSearch(String location, int maxBusiness)
	{
		this(location, maxBusiness, YelpSortParam.DEFAULT);
	}
	
	// Sortable Constructor
	public YelpSearch(String location, int maxBusiness, YelpSortParam sort)
	{
		super();
		this.location = location;
		this.maxBusiness = maxBusiness;
		this.sort = sort;
	}
		
	@Override
	public SearchResults search(String query) {
		Date currentDate = new Date();
		
		ConfigurationManager config = ConfigurationManager.getInstance();
		
		OAuthService oaService = new ServiceBuilder()
		.provider(YelpV2API.class)
		.apiKey(config.getProperty(CONSUMER_KEY))
		.apiSecret(config.getProperty(CONSUMER_SECRET))
		.build();
		
		OAuthRequest oaRequest = 
			new OAuthRequest(Verb.GET, "http://api.yelp.com/v2/search");
		oaRequest.addQuerystringParameter("sort", sort.toString());
		oaRequest.addQuerystringParameter("location", this.location);
		oaRequest.addQuerystringParameter("term", query);
		Token accessToken = new Token(config.getProperty(TOKEN), config.getProperty(TOKEN_SECRET));
		oaService.signRequest(accessToken, oaRequest);
		
		myStartTime = currentDate.getTime();
		Response response = oaRequest.send();
		String rawData = response.getBody();
		try
		{
			logger.info(rawData);
			YelpSearchResult places = new Gson().fromJson(rawData, YelpSearchResult.class);
			String urlQuery = "http://api.yelp.com/v2/business/";
			for (int i=0; i < places.getBusinesses().size() && i < maxBusiness; i++)
			{
				Business bs = places.getBusinesses().get(i);
				logger.info(urlQuery+ bs.getId());
				oaRequest =	new OAuthRequest(Verb.GET, urlQuery + bs.getId());
				oaService.signRequest(accessToken, oaRequest);
				rawData = oaRequest.send().getBody();
				Business bidness = new Gson().fromJson(rawData, Business.class);
				for(Reviews review : bidness.getReviews())
				{
					mySRList.add(new SearchResult("Yelp",
							new Double(bidness.getRating()).toString(),
							new Double(review.getRating()).toString(),
							new Double(review.getRating()),
							bidness.getUrl(),
							review.getExcerpt(),
							bidness.getName(),
							0.0));
				}
				
			}
		} catch(Exception e) {
			logger.error("Error, could not parse returned data!" + e.getMessage());
			logger.debug(rawData);
		}
		myEndTime = currentDate.getTime();
		
		return new SearchResults("Yelp", myEndTime - myStartTime, mySRList);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new YelpSearch("80303").search("Chicken");
	}

}
